/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name          : i2c_ee.c
* Author             : MCD Application Team
* Version            : V2.0.1
* Date               : 06/13/2008
* Description        : This file provides a set of functions needed to manage the
*                      communication between I2C peripheral and I2C M24C08 EEPROM.
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/


/*Driver for AT24C512 eeprom*/
/* Includes ------------------------------------------------------------------*/
#include "i2c_ee.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//#define I2C_Speed              400000
//#define I2C1_SLAVE_ADDRESS7    0xA0
#define I2C_AT24C64_PageSize           32



/*******************************************************************************
* Function Name  : I2C_EE_BufferWrite_Borad
* Description    : Writes buffer of data to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_BufferWrite_Board(I2C_TypeDef *I2Cx, u8 EepromAddr, u8 *pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
    u16 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

    Addr = WriteAddr % I2C_AT24C64_PageSize;
    count = I2C_AT24C64_PageSize - Addr;
    NumOfPage =  NumByteToWrite / I2C_AT24C64_PageSize;
    NumOfSingle = NumByteToWrite % I2C_AT24C64_PageSize;

    /* If WriteAddr is I2C_AT24C64_PageSize aligned  */
    if(Addr == 0)
    {
        /* If NumByteToWrite < I2C_AT24C64_PageSize */
        if(NumOfPage == 0)
        {
            I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, NumOfSingle);
            I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
        }
        /* If NumByteToWrite > I2C_AT24C64_PageSize */
        else
        {
            while(NumOfPage--)
            {
                I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, I2C_AT24C64_PageSize);
                I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
                WriteAddr +=  I2C_AT24C64_PageSize;
                pBuffer += I2C_AT24C64_PageSize;
            }

            if(NumOfSingle != 0)
            {
                I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, NumOfSingle);
                I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
            }

        }
    }
    /* If WriteAddr is not I2C_AT24C64_PageSize aligned  */
    else
    {
        /* If NumByteToWrite < I2C_AT24C64_PageSize */
        if(NumOfPage == 0)
        {
            I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, NumOfSingle);
            I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
        }
        /* If NumByteToWrite > I2C_AT24C64_PageSize */
        else
        {
            NumByteToWrite -= count;
            NumOfPage =  NumByteToWrite / I2C_AT24C64_PageSize;
            NumOfSingle = NumByteToWrite % I2C_AT24C64_PageSize;

            if(count != 0)
            {
                I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, count);
                I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
                WriteAddr += count;
                pBuffer += count;
            }

            while(NumOfPage--)
            {
                I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, I2C_AT24C64_PageSize);
                I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
                WriteAddr +=  I2C_AT24C64_PageSize;
                pBuffer += I2C_AT24C64_PageSize;
            }
            if(NumOfSingle != 0)
            {
                I2C_EE_PageWrite_Board(I2Cx, EepromAddr, pBuffer, WriteAddr, NumOfSingle);
                I2C_EE_WaitEepromStandbyState_Board(I2Cx, EepromAddr);
            }
        }
    }
}

/*******************************************************************************
* Function Name  : I2C_EE_ByteWrite_Board
* Description    : Writes one byte to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_ByteWrite_Board(I2C_TypeDef *I2Cx, u8 EepromAddr, u8 *pBuffer, u16 WriteAddr)
{
    u8 WriteAddr_H;
    u8 WriteAddr_L;

    WriteAddr_H =  (u8)(WriteAddr >> 8 & 0xFF);
    WriteAddr_L =  (u8)(WriteAddr & 0xFF);
    /* Send STRAT condition */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2Cx, EepromAddr, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Send the EEPROM's internal address to write to */

    //I2C_SendData(I2Cx, WriteAddr);
    I2C_SendData(I2Cx, WriteAddr_H);
    /* Test on EV8 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_SendData(I2Cx, WriteAddr_L);
    /* Test on EV8 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send the byte to be written */
    I2C_SendData(I2Cx, *pBuffer);

    /* Test on EV8 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send STOP condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);
}

/*******************************************************************************
* Function Name  : I2C_EE_PageWrite_Board
* Description    : Writes more than one byte to the EEPROM with a single WRITE
*                  cycle. The number of byte can't exceed the EEPROM page size.
* Input          : - pBuffer : pointer to the buffer containing the data to be
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_PageWrite_Board(I2C_TypeDef *I2Cx, u8 EepromAddr, u8 *pBuffer, u16 WriteAddr, u8 NumByteToWrite)
{
    u8 WriteAddr_H;
    u8 WriteAddr_L;

    WriteAddr_H =  (u8)(WriteAddr >> 8 & 0xFF);
    WriteAddr_L =  (u8)(WriteAddr & 0xFF);

    /* Send START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2Cx, EepromAddr, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Send the EEPROM's internal address to write to */

    //I2C_SendData(I2Cx, WriteAddr);
    I2C_SendData(I2Cx, WriteAddr_H);
    /* Test on EV8 and clear it */
    while(! I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_SendData(I2Cx, WriteAddr_L);
    /* Test on EV8 and clear it */
    while(! I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* While there is data to be written */
    while(NumByteToWrite--)
    {
        /* Send the current byte */
        I2C_SendData(I2Cx, *pBuffer);

        /* Point to the next byte to be written */
        pBuffer++;

        /* Test on EV8 and clear it */
        while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    }

    /* Send STOP condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);
}

/*******************************************************************************
* Function Name  : I2C_EE_BufferRead_Board
* Description    : Reads a block of data from the EEPROM.
* Input          : - pBuffer : pointer to the buffer that receives the data read
*                    from the EEPROM.
*                  - ReadAddr : EEPROM's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the EEPROM.
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_BufferRead_Board(I2C_TypeDef *I2Cx, u8 EepromAddr, u8 *pBuffer, u16 ReadAddr, u16 NumByteToRead)
{
    u8 ReadAddr_H;
    u8 ReadAddr_L;

    ReadAddr_H =  (u8)(ReadAddr >> 8 & 0xFF);
    ReadAddr_L =  (u8)(ReadAddr & 0xFF);
    /* Send START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2Cx, EepromAddr, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Clear EV6 by setting again the PE bit */
    I2C_Cmd(I2Cx, ENABLE);

    /* Send the EEPROM's internal address to write to */
    //I2C_SendData(I2Cx, ReadAddr);
    I2C_SendData(I2Cx, ReadAddr_H);
    /* Test on EV8 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_SendData(I2Cx, ReadAddr_L);
    /* Test on EV8 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send STRAT condition a second time */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for read */
    I2C_Send7bitAddress(I2Cx, EepromAddr, I2C_Direction_Receiver);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    /* While there is data to be read */
    while(NumByteToRead)
    {
        if(NumByteToRead == 1)
        {
            /* Disable Acknowledgement */
            I2C_AcknowledgeConfig(I2Cx, DISABLE);

            /* Send STOP Condition */
            I2C_GenerateSTOP(I2Cx, ENABLE);
        }

        /* Test on EV7 and clear it */
        if(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
        {
            /* Read a byte from the EEPROM */
            *pBuffer = I2C_ReceiveData(I2Cx);

            /* Point to the next location where the byte read will be saved */
            pBuffer++;

            /* Decrement the read bytes counter */
            NumByteToRead--;
        }
    }

    /* Enable Acknowledgement to be ready for another reception */
    I2C_AcknowledgeConfig(I2Cx, ENABLE);
}

/*******************************************************************************
* Function Name  : I2C_EE_WaitEepromStandbyState_Board
* Description    : Wait for EEPROM Standby state
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_WaitEepromStandbyState_Board(I2C_TypeDef *I2Cx, u8 EepromAddr)
{
    vu16 SR1_Tmp = 0;

    do
    {
        /* Send START condition */
        I2C_GenerateSTART(I2Cx, ENABLE);
        /* Read I2C1 SR1 register */
        SR1_Tmp = I2C_ReadRegister(I2Cx, I2C_Register_SR1);
        /* Send EEPROM address for write */
        I2C_Send7bitAddress(I2Cx, EepromAddr, I2C_Direction_Transmitter);
    }
    while(!(I2C_ReadRegister(I2Cx, I2C_Register_SR1) & 0x0002));

    /* Clear AF flag */
    I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
}

/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
